package com.cke.yang.storage.api.controller;

import com.cke.yang.common.domain.model.Result;
import com.cke.yang.storage.api.dto.request.StgFileCreateDirectoryRequest;
import com.cke.yang.storage.api.dto.request.StgFileDeleteRequest;
import com.cke.yang.storage.api.dto.request.StgFileListRequest;
import com.cke.yang.storage.api.dto.request.StgFileRenameRequest;
import com.cke.yang.storage.api.dto.response.FileDownloadResponse;
import com.cke.yang.storage.api.dto.response.StgFileListResponse;
import com.cke.yang.storage.app.service.StgFileService;
import com.cke.yang.storage.domain.entity.StgFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 存储模块-文件控制器
 *
 * @author yuyang
 */
@RestController
@RequestMapping("/api/storage/stg-file")
@Slf4j
public class StgFileController {

    @Autowired
    private StgFileService stgFileService;

    /**
     * 获取文件列表
     *
     * @param request 查询请求参数
     * @return 文件列表
     */
    @PostMapping("/list")
    public Result<List<StgFileListResponse>> list(@RequestBody StgFileListRequest request) {
        List<StgFileListResponse> files = stgFileService.list(request);
        return Result.success(files);
    }

    /**
     * 批量上传文件
     *
     * @param files 上传的文件列表
     * @param sourceId 存储源ID
     * @param uploadPathBase64 上传路径(Base64编码)
     * @return 上传成功的文件记录列表
     */
    @PostMapping("/upload")
    public Result<List<StgFile>> upload(@RequestParam("files") MultipartFile[] files,
                                        @RequestParam("sourceId") Long sourceId,
                                        @RequestParam(value = "uploadPathBase64", required = false) String uploadPathBase64) {
        try {
            List<StgFile> uploadedFiles = stgFileService.upload(files, sourceId, uploadPathBase64);
            return Result.success(uploadedFiles);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return Result.fail("500", "文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 根据文件Key下载文件
     *
     * @param fileKey 文件Key
     * @return 文件流响应
     */
    @GetMapping("/download")
    public ResponseEntity<Resource> download(@RequestParam("fileKey") String fileKey) {
        try {
            // 调用服务层下载方法
            FileDownloadResponse downloadResult = stgFileService.downloadByFileKey(fileKey);

            // 构建响应头
            HttpHeaders headers = new HttpHeaders();

            // 设置Content-Type
            headers.setContentType(MediaType.parseMediaType(downloadResult.getContentType()));

            // 设置文件名，支持中文文件名
            String encodedFileName = encodeFileName(downloadResult.getFileName());
            headers.setContentDispositionFormData("attachment", encodedFileName);

            // 设置文件大小
            headers.setContentLength(downloadResult.getFileSize());

            // 设置缓存控制
            headers.setCacheControl("no-cache, no-store, must-revalidate");
            headers.setPragma("no-cache");
            headers.setExpires(0);

            log.info("文件下载请求成功: fileKey={}, fileName={}", fileKey, downloadResult.getFileName());

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(downloadResult.getResource());

        } catch (Exception e) {
            log.error("文件下载失败: fileKey={}", fileKey, e);
            // 返回错误响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            return ResponseEntity.badRequest()
                    .headers(headers)
                    .body(null);
        }
    }

    /**
     * 创建目录
     *
     * @param request 创建目录请求参数
     * @return 创建的目录文件记录
     */
    @PostMapping("/mkdir")
    public Result<StgFile> createDirectory(@RequestBody StgFileCreateDirectoryRequest request) {
        try {
            StgFile directory = stgFileService.mkdir(
                    request.getSourceId(),
                    request.getDirectoryName(),
                    request.getParentPath()
            );
            return Result.success(directory);
        } catch (Exception e) {
            log.error("创建目录失败", e);
            return Result.fail("500", "创建目录失败: " + e.getMessage());
        }
    }

    /**
     * 删除文件
     *
     * @param request 删除文件请求参数
     * @return 删除结果
     */
    @PostMapping("/remove")
    public Result<Boolean> remove(@RequestBody StgFileDeleteRequest request) {
        List<String> fileKeyList = request.getFileKeyList();
        if (CollectionUtils.isEmpty(fileKeyList)) {
            return Result.fail("404", "未指定需要删除的文件");
        }
        try {
            for (String fileKey : fileKeyList) {
                stgFileService.remove(fileKey);
            }
            return Result.success(true);
        } catch (Exception e) {
            log.error("删除文件失败", e);
            return Result.fail("500", "删除文件失败: " + e.getMessage());
        }
    }

    /**
     * 重命名文件
     *
     * @param request 重命名文件请求参数
     * @return 重命名后的文件记录
     */
    @PostMapping("/rename")
    public Result<StgFile> rename(@RequestBody StgFileRenameRequest request) {
        try {
            StgFile renamedFile = stgFileService.rename(request.getFileKey(), request.getNewFileName());
            return Result.success(renamedFile);
        } catch (Exception e) {
            log.error("重命名文件失败", e);
            return Result.fail("500", "重命名文件失败: " + e.getMessage());
        }
    }

    /**
     * 编码文件名以支持中文
     *
     * @param fileName 原始文件名
     * @return 编码后的文件名
     */
    private String encodeFileName(String fileName) {
        try {
            return URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            log.warn("文件名编码失败，使用原始文件名: {}", fileName);
            return fileName;
        }
    }

}
